home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / CBGRX103.ZIP / contrib / libgrx / src / drawtext.c < prev    next >
Text File  |  1993-12-06  |  10KB  |  353 lines

  1. /**
  2.  ** DRAWTEXT.C
  3.  **
  4.  **  Copyright (C) 1992, Csaba Biegl
  5.  **    820 Stirrup Dr, Nashville, TN, 37221
  6.  **    csaba@vuse.vanderbilt.edu
  7.  **
  8.  **  This file is distributed under the terms listed in the document
  9.  **  "copying.cb", available from the author at the address above.
  10.  **  A copy of "copying.cb" should accompany this file; if not, a copy
  11.  **  should be available from where this file was obtained.  This file
  12.  **  may not be distributed without a verbatim copy of "copying.cb".
  13.  **  You should also have received a copy of the GNU General Public
  14.  **  License along with this program (it is in the file "copying");
  15.  **  if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16.  **  Cambridge, MA 02139, USA.
  17.  **
  18.  **  This program is distributed in the hope that it will be useful,
  19.  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  **  GNU General Public License for more details.
  22.  **/
  23.  
  24. #include "grx.h"
  25. #include "libgrx.h"
  26. #include "grxfont.h"
  27. #include "clipping.h"
  28. #include "gmalloc.h"
  29. #include "memfill.h"
  30. #include "memcopy.h"
  31. #include <string.h>
  32.  
  33.  
  34. #define TXT_CLIP    1
  35. #define TXT_NORMAL  0
  36. #define TXT_ONEPIX  2
  37. #define TXT_LARGE   4
  38.  
  39.  
  40. #define BUILDMAT(m00,m01,m10,m11) \
  41.     { mat00 = m00; mat01 = m01; mat10 = m10; mat11 = m11; }
  42. #define MMULT_X(_x,_y)  (mat00*(_x) + mat01*(_y))
  43. #define MMULT_Y(_x,_y)  (mat10*(_x) + mat11*(_y))
  44. /*
  45. #define UPDATE_X(x,y)    x += MMULT_X(1,0),y += MMULT_Y(1,0)
  46. #define UPDATE_Y(x,y)    x += MMULT_X(0,1),y += MMULT_Y(0,1)
  47. */
  48. #define UPDATE_X(x,y)    x += mat00,y += mat10
  49. #define UPDATE_Y(x,y)    x += mat01,y += mat11
  50.  
  51.  
  52. #define GETBITS()    if((mask >>= 1) == 0) { bits = *bitmap++; mask = 0x80; }
  53.  
  54. void GrDrawString(char *text,int length,int x,int y,GrTextOption *opt)
  55. {
  56.     GrFont *f = CHECK_FONT(opt->txo_font);
  57.     GrColorTableP fgcp,bgcp;
  58.     char far *bitmap,*tempp = NULL;
  59.     int  type = opt->txo_chrtype;
  60.     int  needs_clipping;
  61.     int  mode,mode2,fixed;
  62.     int  xchr,chr,attr;
  63.     int  width,height;
  64.     int  mat00,mat01;
  65.     int  mat10,mat11;
  66.     int  pixww,pixhh;
  67.     int  pixdx,pixdy;
  68.     int  chrww,chrhh;
  69.     int  chrdx,chrdy;
  70.     int  x1,x2,y1,y2;
  71.     int  xdot,ydot;
  72.     int  bits,mask;
  73.     int  fgc,bgc;
  74.     int  underline = 0;
  75.     int  ww,hh;
  76.     MOUSE_FLAG;
  77.  
  78.     if((f == NULL) ||
  79.        (_GrGetTextSize(text,length,&width,&height,opt) == FALSE) ||
  80.        (width  == 0) ||
  81.        (height == 0))
  82.         return;
  83.     if((ww = width)  < 0) { ww = (-ww); x += (ww - 1); }
  84.     if((hh = height) < 0) { hh = (-hh); y += (hh - 1); }
  85.     switch(opt->txo_xalign) {
  86.       case GR_ALIGN_RIGHT:
  87.         x -= (ww - 1);
  88.         break;
  89.       case GR_ALIGN_CENTER:
  90.         x -= (ww >> 1);
  91.         break;
  92.     }
  93.     switch(opt->txo_yalign) {
  94.       case GR_ALIGN_BASELINE:
  95.         if(opt->txo_direct == GR_TEXT_DEFAULT) y -= f->fnt_baseline;
  96.         break;
  97.       case GR_ALIGN_BOTTOM:
  98.         y -= (hh - 1);
  99.         break;
  100.       case GR_ALIGN_CENTER:
  101.         y -= (hh >> 1);
  102.         break;
  103.     }
  104.     x2 = (x1 = x) + width  + ((width  > 0) ? (-1) : 1);
  105.     y2 = (y1 = y) + height + ((height > 0) ? (-1) : 1);
  106.     needs_clipping = FALSE;
  107. #undef  WHEN_CLIPPED
  108. #define WHEN_CLIPPED    needs_clipping = TRUE
  109.     CLIPBOX(CURC,x1,y1,x2,y2);
  110.     MOUSE_BLOCK(CURC,x1,y1,x2,y2);
  111.     switch(type) {
  112.       case GR_ATTR_TEXT:
  113.         attr = (-1);
  114.         fgcp = opt->txo_fgcolor.p;
  115.         bgcp = opt->txo_bgcolor.p;
  116.         break;
  117.       case GR_WORD_TEXT:
  118.       default:
  119.         fgc = opt->txo_fgcolor.v;
  120.         bgc = opt->txo_bgcolor.v;
  121.         if(fgc & GR_UNDERLINE_TEXT) {
  122.         fgc &= ~GR_UNDERLINE_TEXT;
  123.         underline = f->fnt_undwidth;
  124.         }
  125.         if((fgc & (GrXOR | GrOR | GrAND)) == GrWRITE) {
  126.         _GrSetPixBlock(PIXEL_ADDR(x1,y1),bgc,x2-x1+1,y2-y1+1);
  127.         bgc = GrNOCOLOR;
  128.         }
  129.     }
  130.     switch(opt->txo_direct) {
  131.       case GR_TEXT_DOWN:
  132.         mode  = TXT_ONEPIX;
  133.         pixww = opt->txo_ymag;
  134.         pixhh = opt->txo_xmag;
  135.         BUILDMAT(0,-pixww,pixhh,0);
  136.         break;
  137.       case GR_TEXT_LEFT:
  138.         mode  = TXT_ONEPIX;
  139.         pixww = opt->txo_xmag;
  140.         pixhh = opt->txo_ymag;
  141.         BUILDMAT(-pixww,0,0,-pixhh);
  142.         break;
  143.       case GR_TEXT_UP:
  144.         mode  = TXT_ONEPIX;
  145.         pixww = opt->txo_ymag;
  146.         pixhh = opt->txo_xmag;
  147.         BUILDMAT(0,pixww,-pixhh,0);
  148.         break;
  149.       default:
  150.         mode  = TXT_NORMAL;
  151.         pixww = opt->txo_xmag;
  152.         pixhh = opt->txo_ymag;
  153.         BUILDMAT(pixww,0,0,pixhh);
  154.         break;
  155.     }
  156.     if((pixww > 1) || (pixhh > 1)) mode = TXT_LARGE;
  157.     if((pixdx = MMULT_X(1,1)) > 0) pixdx = 0; else pixdx++;
  158.     if((pixdy = MMULT_Y(1,1)) > 0) pixdy = 0; else pixdy++;
  159.     if((fixed = f->fnt_isfixed) != FALSE) {
  160.         width  = f->fnt_width;
  161.         height = f->fnt_height;
  162.         chrdx  = MMULT_X(width,0);
  163.         chrdy  = MMULT_Y(width,0);
  164.         if((chrww = MMULT_X(width,height)) > 0) chrww--; else chrww++;
  165.         if((chrhh = MMULT_Y(width,height)) > 0) chrhh--; else chrhh++;
  166.     }
  167.     mode2 = mode;
  168.     while(--length >= 0) {
  169.         switch(type) {
  170.           case GR_WORD_TEXT:
  171.         chr = *((unsigned short *)text)++;
  172.         break;
  173.           case GR_ATTR_TEXT:
  174.         xchr  = *((short *)text)++;
  175.         chr   = xchr & 0xff;
  176.         if(attr != (xchr &= 0xff00)) {
  177.             fgc  = (xchr >> 8)  & 0x0f;
  178.             bgc  = (xchr >> 12) & 0x07;
  179.             fgc  = GR_CTABLE_COLOR(fgcp,fgc);
  180.             bgc  = GR_CTABLE_COLOR(bgcp,bgc);
  181.             underline = (xchr & 0x8000) ? f->fnt_undwidth : 0;
  182.             attr = xchr;
  183.         }
  184.         break;
  185.           default:
  186.         chr = *((unsigned char *)text)++;
  187.         break;
  188.         }
  189.         if((chr > f->fnt_maxchar) || ((chr -= f->fnt_minchar) < 0)) {
  190.         if(fixed) {
  191.             x1 = x; x2 = x + chrww; x += chrdx;
  192.             y1 = y; y2 = y + chrhh; y += chrdy;
  193.             if(bgc == GrNOCOLOR) continue;
  194.             SORT2(x1,x2);
  195.             SORT2(y1,y2);
  196. #undef  WHEN_OUTSIDE
  197. #undef  WHEN_CLIPPED
  198. #define WHEN_OUTSIDE    continue
  199. #define WHEN_CLIPPED
  200.             if(needs_clipping) CLIPSORTEDBOX(CURC,x1,y1,x2,y2);
  201.             _GrSetPixBlock(PIXEL_ADDR(x1,y1),bgc,x2-x1+1,y2-y1+1);
  202.         }
  203.         continue;
  204.         }
  205.         if(fixed)
  206.         bitmap = FFP(f)->ff_bits + (chr * FFP(f)->ff_chrsize);
  207.         else {
  208.         bitmap = PFP(f)->pf_bits[chr];
  209.         width  = PFP(f)->pf_width[chr];
  210.         height = f->fnt_height;
  211.         chrdx  = MMULT_X(width,0);
  212.         chrdy  = MMULT_Y(width,0);
  213.         if((chrww = MMULT_X(width,height)) > 0) chrww--; else chrww++;
  214.         if((chrhh = MMULT_Y(width,height)) > 0) chrhh--; else chrhh++;
  215.         }
  216.         if(underline > 0) {
  217.         if(tempp == NULL)
  218.             tempp = _GrGetTempBuffer((fixed ? width : PFP(f)->pf_maxwidth) * height);
  219.         if(tempp != NULL) {
  220.             _ClrDir();
  221.             ww = (width + 7) >> 3;
  222.             hh = height - underline;
  223.             _SaveDS();
  224.             _RowCpyB(TXT,tempp,bitmap,(ww * hh));
  225.             _RestoreDS();
  226.             bitmap = &tempp[ww * hh];
  227.             _SaveDS();
  228.             _RowSetB(TXT,bitmap,0xff,(ww * underline));
  229.             _RestoreDS();
  230.             bitmap = tempp;
  231.         }
  232.         }
  233.         xdot = x; x += chrdx;
  234.         ydot = y; y += chrdy;
  235.         if(needs_clipping) {
  236.         x1 = xdot; x2 = xdot + chrww;
  237.         y1 = ydot; y2 = ydot + chrhh;
  238.         mode2 = mode;
  239. #undef  WHEN_CLIPPED
  240. #define WHEN_CLIPPED    mode2 |= TXT_CLIP
  241.         CLIPBOX(CURC,x1,y1,x2,y2);
  242.         }
  243.         xdot += pixdx;
  244.         ydot += pixdy;
  245.         switch(mode2) {
  246.           case TXT_NORMAL:
  247.         _GrDrawChar(PIXEL_ADDR(xdot,ydot),width,height,bitmap,fgc,bgc);
  248.         break;
  249.           case TXT_ONEPIX:
  250.         for(hh = height; --hh >= 0; UPDATE_Y(xdot,ydot)) {
  251.             x1 = xdot; y1 = ydot;
  252.             for(mask = 0,ww = width; --ww >= 0; UPDATE_X(x1,y1)) {
  253.             GETBITS();
  254.             if(bits & mask) {
  255.                 _GrSetPixel(PIXEL_ADDR(x1,y1),fgc);
  256.             }
  257.             else if(bgc != GrNOCOLOR) {
  258.                 _GrSetPixel(PIXEL_ADDR(x1,y1),bgc);
  259.             }
  260.             }
  261.         }
  262.         break;
  263.           case (TXT_NORMAL | TXT_CLIP):
  264.           case (TXT_ONEPIX | TXT_CLIP):
  265.         for(hh = height; --hh >= 0; UPDATE_Y(xdot,ydot)) {
  266.             x1 = xdot; y1 = ydot;
  267.             for(mask = 0,ww = width; --ww >= 0; UPDATE_X(x1,y1)) {
  268.             GETBITS();
  269. #undef  WHEN_CLIPPED
  270. #define WHEN_CLIPPED
  271.             CLIPDOT(CURC,x1,y1);
  272.             if(bits & mask) {
  273.                 _GrSetPixel(PIXEL_ADDR(x1,y1),fgc);
  274.             }
  275.             else if(bgc != GrNOCOLOR) {
  276.                 _GrSetPixel(PIXEL_ADDR(x1,y1),bgc);
  277.             }
  278.             }
  279.         }
  280.         break;
  281.           case TXT_LARGE:
  282.         for(hh = height; --hh >= 0; UPDATE_Y(xdot,ydot)) {
  283.             x1 = xdot; y1 = ydot;
  284.             for(mask = 0,ww = width; --ww >= 0; UPDATE_X(x1,y1)) {
  285.             GETBITS();
  286.             if(bits & mask) {
  287.                 _GrSetPixBlock(PIXEL_ADDR(x1,y1),fgc,pixww,pixhh);
  288.             }
  289.             else if(bgc != GrNOCOLOR) {
  290.                 _GrSetPixBlock(PIXEL_ADDR(x1,y1),bgc,pixww,pixhh);
  291.             }
  292.             }
  293.         }
  294.         break;
  295.           case (TXT_LARGE | TXT_CLIP):
  296.         for(hh = height; --hh >= 0; UPDATE_Y(xdot,ydot)) {
  297.             int x0 = xdot, y0 = ydot;
  298.             for(mask = 0,ww = width; --ww >= 0; UPDATE_X(x0,y0)) {
  299.             GETBITS();
  300.             x2 = (x1 = x0) + pixww - 1;
  301.             y2 = (y1 = y0) + pixhh - 1;
  302.             CLIPSORTEDBOX(CURC,x1,y1,x2,y2);
  303.             if(bits & mask) {
  304.                 _GrSetPixBlock(PIXEL_ADDR(x1,y1),
  305.                 fgc,
  306.                 (x2 - x1 + 1),
  307.                 (y2 - y1 + 1)
  308.                 );
  309.             }
  310.             else if(bgc != GrNOCOLOR) {
  311.                 _GrSetPixBlock(PIXEL_ADDR(x1,y1),
  312.                 bgc,
  313.                 (x2 - x1 + 1),
  314.                 (y2 - y1 + 1)
  315.                 );
  316.             }
  317.             }
  318.         }
  319.         break;
  320.         }
  321.     }
  322.     MOUSE_UNBLOCK();
  323. }
  324.  
  325. void GrDrawChar(int chr,int x,int y,GrTextOption *opt)
  326. {
  327.     char  cbuff[2];
  328.     short sbuff[2];
  329.  
  330.     switch(opt->txo_chrtype) {
  331.       case GR_WORD_TEXT:
  332.       case GR_ATTR_TEXT:
  333.         sbuff[0] = chr;
  334.         GrDrawString((char *)sbuff,1,x,y,opt);
  335.         break;
  336.       default:
  337.         cbuff[0] = chr;
  338.         GrDrawString(cbuff,1,x,y,opt);
  339.         break;
  340.     }
  341. }
  342.  
  343. void GrTextXY(int x,int y,char *text,int fg,int bg)
  344. {
  345.     static GrTextOption opt = { NULL, 1, 1, 0 };
  346.  
  347.     if(opt.txo_font == NULL) opt.txo_font = CHECK_FONT(NULL);
  348.     opt.txo_fgcolor.v = fg;
  349.     opt.txo_bgcolor.v = bg;
  350.     GrDrawString(text,strlen(text),x,y,&opt);
  351. }
  352.  
  353.